package event

import (
	"fmt"
	"path/filepath"
	"plugin"
	"strings"
	"sync"
)

// PluginInfo 插件信息
type PluginInfo struct {
	createFunc func(*PluginContext) EventProcessor // 插件创建函数
	Path       string                              // 插件文件路径
}

// PluginReader 插件读取器
type PluginReader struct {
	plugins map[string]PluginInfo
	mu      sync.RWMutex
}

// NewPluginReader 创建新的插件读取器
func NewPluginReader() *PluginReader {
	return &PluginReader{
		plugins: make(map[string]PluginInfo),
	}
}

func (pr *PluginReader) Read(folder string) error {
	return pr.LoadPlugins(folder)
}

// LoadPlugins 从指定文件夹加载插件
func (pr *PluginReader) LoadPlugins(folder string) error {
	files, err := filepath.Glob(filepath.Join(folder, "*.so"))
	if err != nil {
		return err
	}

	for _, file := range files {
		p, err := plugin.Open(file)
		if err != nil {
			fmt.Printf("Skip plugin %s, err: %v\n", file, err)
			continue
		}

		sym, err := p.Lookup("CreatePlugin")
		if err != nil {
			fmt.Printf("Skip plugin %s, err: %v\n", file, err)
			continue
		}

		createPlugin, ok := sym.(func(*PluginContext) EventProcessor)
		if !ok {
			fmt.Printf("Skip plugin %s\n", file)
			continue
		}

		filename := filepath.Base(file)
		name := strings.TrimSuffix(filename, ".so")

		pr.mu.Lock()
		fmt.Println("Load plugin:", filename)
		pr.plugins[name] = PluginInfo{
			createFunc: createPlugin,
			Path:       file,
		}
		pr.mu.Unlock()
	}

	return nil
}

// Create 创建插件事件处理器
func (pr *PluginReader) Create(name string, ctx *PluginContext) (EventProcessor, error) {
	pr.mu.RLock()
	pluginInfo, exists := pr.plugins[name]
	pr.mu.RUnlock()

	if !exists {
		return nil, fmt.Errorf("plugin %s not found", name)
	}

	return pluginInfo.createFunc(ctx), nil
}

// Len 获取已加载插件的数量
func (pr *PluginReader) Len() int {
	pr.mu.RLock()
	defer pr.mu.RUnlock()
	return len(pr.plugins)
}

// Names 获取所有已加载插件的名称列表
func (pr *PluginReader) Names() []string {
	pr.mu.RLock()
	defer pr.mu.RUnlock()

	names := make([]string, 0, len(pr.plugins))
	for name := range pr.plugins {
		names = append(names, name)
	}
	return names
}

// GetPluginInfo 获取插件信息
func (pr *PluginReader) GetPluginInfo(name string) (PluginInfo, bool) {
	pr.mu.RLock()
	defer pr.mu.RUnlock()

	pluginInfo, exists := pr.plugins[name]
	return pluginInfo, exists
}

// Path 获取插件的文件路径
func (pr *PluginReader) Path(name string) (string, bool) {
	pr.mu.RLock()
	defer pr.mu.RUnlock()

	pluginInfo, exists := pr.plugins[name]
	return pluginInfo.Path, exists
}
